home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Inspectors / InspectorManager / InspectorManager.m < prev    next >
Text File  |  1995-06-12  |  11KB  |  370 lines

  1. // InspectorManager.m
  2. // By Kevin Brain
  3. // A class for managing an inspector.
  4. // Compositing techniques and functions from the ToolInspector example
  5. // by Sharon Biocca Zakhour, NeXT Developer Support Team
  6. // You may freely copy, distribute and reuse the code in this example.  
  7. // *Everybody involved* disclaims any warranty of any kind, expressed 
  8. // or implied, as to its fitness for any particular use.
  9.  
  10. #import <objc/NXStringTable.h>
  11. #import <appkit/Panel.h>
  12. #import <appkit/View.h>
  13. #import <appkit/PopUpList.h>
  14. #import <appkit/Matrix.h>
  15. #import <objc/Storage.h>
  16. #import <objc/List.h>
  17. #import <appkit/Application.h>    // for NXApp
  18. #import <dpsclient/wraps.h>        // PScomposite
  19. #import <libc.h>
  20.  
  21. #import "InspectorManager.h"
  22. #define INTERVIEWSPACING 2
  23.  
  24. @implementation InspectorManager
  25.  
  26. /* Private functions */
  27. static void 
  28. compositeToBuffer(InspectorManager *self, float srcX, float srcY, float width, 
  29.   float height, float dstX, float dstY)
  30. {
  31.     [[self->layouts contentView] lockFocus];
  32.     PScomposite(srcX, srcY, width, height,
  33.         [[self->inspectorPanel contentView] gState], dstX, dstY, NX_COPY);
  34.     [[self->layouts contentView] unlockFocus];
  35. }
  36.  
  37. static void 
  38. compositeToScreen(InspectorManager *self, float srcX, float srcY, float width, 
  39.   float height, float dstX, float dstY)
  40. {
  41.     [[self->inspectorPanel contentView] lockFocus];
  42.     PScomposite(srcX, srcY, width, height, 
  43.         [[self->layouts contentView] gState], dstX, dstY, NX_COPY);
  44.     [self->inspectorPanel flushWindow];
  45.     [[self->inspectorPanel contentView] unlockFocus];
  46. }
  47.  
  48. /* instance methods */
  49.  
  50. - init
  51. {
  52.     [super init];
  53.     if ([NXApp loadNibSection:"Inspector.nib" owner:self] == nil)
  54.         NXRunAlertPanel(NULL,"Couldn't load Inspector.nib","OK",NULL,NULL);
  55.     /* Tell the Inspector & Palette panels not to become the key window */
  56.     [inspectorPanel setBecomeKeyOnlyIfNeeded: YES];   /* This will only */
  57.         /* work if you don't miniaturize the panel. */
  58.     [inspectorPanel setFloatingPanel:(BOOL)YES];
  59.     useKeyEquivalents = YES;
  60.     
  61.     inspectorList = [[Storage alloc] initCount:0 elementSize:sizeof(struct inspectorListEntry) description:"@*"];
  62.     groupList = [[Storage alloc] initCount:0 elementSize:sizeof(struct inspectorListEntry) description:"@*"];
  63.     visibleInspectors = [[Storage alloc] initCount:0 elementSize:sizeof(unsigned int) description:"i"];
  64.     [revertOKOut removeFromSuperview];
  65.     [popupOut removeFromSuperview];
  66.     [inspectorPanel display];            // to actually remove the controls
  67.     /* 'layouts' is created in IB as the window containing all the */
  68.     /* default inspectors side by side. */
  69.     /* This window is non-deferred and always kept off-screen */
  70.     [[[layouts contentView] allocateGState] lockFocus]; /* The lockFocus forces the */
  71.     [[layouts contentView] unlockFocus];                /* gState to become defined */
  72.     [[inspectorPanel contentView] allocateGState];
  73.  
  74.     [self addInspector: noInspectorBox 
  75.         title:[inspectorStrings valueForStringKey: "NoSelectionInspector"]];
  76.     [self addInspector: multiInspectorBox 
  77.         title:[inspectorStrings valueForStringKey: "MultiSelectionInspector"]];
  78.     [self addInspector: unapplicableInspectorBox 
  79.         title:[inspectorStrings valueForStringKey: "UnapplicableInspector"]];
  80.  
  81.     /* Initialize the Inspector to the "Unapplicable Inspector" state */
  82.     [self switchToInspector:(unsigned int)NOTAPPLICABLE];
  83.  
  84.     return self;
  85. }
  86.  
  87. - (unsigned int)addInspector:(id)theView title:(const char *)theTitle
  88. {
  89.     return [self addInspector:theView title:theTitle atLocation:LOWERLEFTX :LOWERLEFTY];
  90. }
  91.  
  92. - (unsigned int)addInspector:(id)theView title:(const char *)theTitle atLocation:(NXCoord)xLoc :(NXCoord)yLoc
  93. {
  94.     struct inspectorListEntry tempInspectorEntry;
  95.     NXRect    theViewRect, cvRect;
  96.     
  97.     tempInspectorEntry.view = theView;
  98.     tempInspectorEntry.showing = NO;
  99.     tempInspectorEntry.title = malloc(sizeof(char)*(strlen((char *)theTitle)));
  100.     strcpy(tempInspectorEntry.title,theTitle);
  101.  
  102.     [theView getFrame:&theViewRect];
  103.     [[layouts contentView] getFrame:&cvRect];
  104.     [[layouts contentView] addSubview:theView];
  105.     if ((lastRect.origin.y+lastRect.size.height+ theViewRect.size.height+INTERVIEWSPACING) >= cvRect.size.height) {
  106.         [layouts sizeWindow:(NXCoord)(cvRect.size.width + theViewRect.size.width + INTERVIEWSPACING)
  107.             :(NXCoord)cvRect.size.height];
  108.         lastRect.origin.x = cvRect.size.width;
  109.         lastRect.origin.y = 0;
  110.         }
  111.     else {
  112.         if ((lastRect.origin.x + theViewRect.size.width  + INTERVIEWSPACING) >= cvRect.size.width)
  113.             [layouts sizeWindow:(NXCoord)(lastRect.origin.x + theViewRect.size.width + INTERVIEWSPACING)
  114.                 :(NXCoord)cvRect.size.height];
  115.         lastRect.origin.y = lastRect.origin.y + lastRect.size.height + INTERVIEWSPACING;
  116.         }
  117.     lastRect.size = theViewRect.size;
  118.     [theView moveTo:lastRect.origin.x :lastRect.origin.y];
  119.     [theView display];
  120.     [theView getFrame:&tempInspectorEntry.offscreenRect];
  121.             
  122.     [inspectorList addElement:&tempInspectorEntry];
  123.     
  124.     [theView moveTo:xLoc :yLoc];
  125.     [theView removeFromSuperview];
  126.     return [inspectorList count]-1;
  127. }
  128.  
  129. - (unsigned int)addGroup:(const char *)theTitle
  130. {
  131.     struct inspectorListEntry tempGroupEntry;
  132.     unsigned short temp;
  133.     
  134.     // add item to PopUpList
  135.     if (([groupList count] < 9) && (useKeyEquivalents == YES))    // command-key equivalents for first 9
  136.         temp = (unsigned short)[groupList count]+(unsigned short)'1';
  137.     else
  138.         temp = 0;    // no command-key equivalent for rest
  139.     tempGroupEntry.view = [[popupOut target] addItem:theTitle 
  140.                         action:@selector(selectGroup:)
  141.                         keyEquivalent:temp];
  142.     [tempGroupEntry.view  setTarget:self];
  143.     if ([groupList count] == 0) {
  144.         // remove the default 'None' item in PopUpList
  145.         [[popupOut target] removeItemAt:(unsigned int)0];
  146.         [popupOut setTitle:theTitle];
  147.         }
  148.     if ([groupList count] == 1)
  149.         [self showGroupPopUp];
  150.     tempGroupEntry.title = malloc(sizeof(char)*(strlen((char *)theTitle)));
  151.     strcpy(tempGroupEntry.title,theTitle);
  152.     [groupList addElement:&tempGroupEntry];
  153.     return [groupList count]-1;
  154. }
  155.  
  156. - setUseKeyEquivalents:(BOOL)use
  157. {
  158.     useKeyEquivalents = use;
  159.     return self;
  160. }
  161.  
  162. - switchToInspector:(unsigned int)newInspector
  163. {
  164.     struct inspectorListEntry *new,*tempOld;
  165.     View *tempView;
  166.     NXRect tempFrame;
  167.     int i,*tempShowing;
  168.     unsigned cnt = [visibleInspectors count];
  169.     
  170.     new = [inspectorList elementAt:newInspector];
  171.     if (!new) return self;    // not a valid inspector
  172.     if (new->showing == YES) return self;        // if already showing
  173.     /* remove all other inspectors */
  174.     if (cnt)            
  175.         for (i=(int)cnt; i > 0;i--) {
  176.             tempShowing = [visibleInspectors elementAt:i-1];
  177.             tempOld = [inspectorList elementAt:(unsigned int)*tempShowing];
  178.             tempOld->showing = NO;
  179.             tempView = tempOld->view;
  180.             if (tempView != NULL) {
  181.                 [tempView getFrame:&tempFrame];
  182.                 compositeToBuffer(self, tempFrame.origin.x, tempFrame.origin.y, NX_WIDTH(&tempFrame), 
  183.                     NX_HEIGHT(&tempFrame), tempOld->offscreenRect.origin.x, tempOld->offscreenRect.origin.y);
  184.                 [tempView removeFromSuperview];
  185.                 }
  186.             }
  187.     [visibleInspectors empty];
  188.  
  189.     [[inspectorPanel contentView] addSubview:new->view];
  190.     /* Now composite the new tool view from the offscreen window into the */
  191.     /* toolInspector */
  192.     [new->view getFrame:&tempFrame];
  193.     compositeToScreen(self, new->offscreenRect.origin.x, new->offscreenRect.origin.y, 
  194.         NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y);
  195.     
  196.     [inspectorPanel setTitle:new->title];
  197.     new->showing = YES;
  198.     i=(int)newInspector;
  199.     [visibleInspectors addElement:&i];
  200.     
  201.     return self;
  202. }
  203.  
  204. - showInspector:(unsigned int)newInspector
  205. {
  206.     struct inspectorListEntry *new;
  207.     NXRect tempFrame;
  208.     int tempNum;
  209.     
  210.     new = [inspectorList elementAt:newInspector];
  211.     if (!new) return self;    // not a valid inspector
  212.  
  213.     if ([self showing:newInspector] == YES) return self;        // if already showing
  214.  
  215.     [inspectorPanel disableFlushWindow];
  216.     [[inspectorPanel contentView] addSubview:new->view];
  217.     /* Now composite the new tool view from the offscreen window into the */
  218.     /* toolInspector */
  219.     [new->view getFrame:&tempFrame];
  220.     compositeToScreen(self, new->offscreenRect.origin.x, new->offscreenRect.origin.y, 
  221.         NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y);
  222.     
  223.     [inspectorPanel setTitle:new->title];
  224.     [inspectorPanel reenableFlushWindow];
  225.     [inspectorPanel flushWindowIfNeeded];
  226.     new->showing = YES;
  227.     tempNum = (int)newInspector;
  228.     [visibleInspectors addElement:&tempNum];
  229.     
  230.     return self;
  231. }
  232.  
  233. - hideInspector:(unsigned int)inspectorNum
  234. {
  235.     struct inspectorListEntry *new;
  236.     View *tempView;
  237.     NXRect tempFrame;
  238.     int i,cnt = [visibleInspectors count],*tempNum;
  239.     
  240.     new = [inspectorList elementAt:inspectorNum];
  241.     if (!new) return self;    // not a valid inspector
  242.     if(cnt)            // find inspectorNum is visibleInspectors list
  243.         for (i=cnt; i > 0;i--) {
  244.             tempNum = [visibleInspectors elementAt:i-1];
  245.             if (inspectorNum == (unsigned)*tempNum) {
  246.                 [visibleInspectors removeAt:(unsigned)i-1];
  247.                 new->showing = NO;
  248.                 tempView = new->view;
  249.                 if (tempView != NULL) {
  250.                     [tempView getFrame:&tempFrame];
  251.                     compositeToBuffer(self, tempFrame.origin.x, tempFrame.origin.y, NX_WIDTH(&tempFrame), 
  252.                         NX_HEIGHT(&tempFrame), new->offscreenRect.origin.x, new->offscreenRect.origin.y);
  253.                     [tempView removeFromSuperview];
  254.                     }
  255.                 }
  256.             }
  257.         
  258.     return self;
  259. }
  260.  
  261. - (BOOL)showing:(unsigned int)inspectorNum
  262. {
  263.     struct inspectorListEntry *new;
  264.     
  265.     if (inspectorNum >= [inspectorList count]) return NO;    // not a valid inspector
  266.     else new = [inspectorList elementAt:(unsigned)inspectorNum];
  267.  
  268.     if (new->showing == YES) return YES;
  269.     else return NO;
  270. }
  271.  
  272. - (int)group
  273. {
  274.     // check if a group is selected (none is initially)
  275.     if ([[popupOut target] selectedItem] == NULL)
  276.         return 0;    // if no group selected, return default group (first group added)
  277.     else
  278.         return [[popupOut target] indexOfItem:[[popupOut target] selectedItem]];
  279. }
  280.  
  281. - panel
  282. {
  283.     return inspectorPanel;
  284. }
  285.  
  286. - popUpListButton
  287. {
  288.     return popupOut;
  289. }
  290.  
  291. - revertOKMatrix
  292. {
  293.     return revertOKOut;
  294. }
  295.  
  296. - setDelegate:(id)anObject
  297. {
  298.     delegate = anObject;
  299.     return self;
  300. }
  301.  
  302. - delegate
  303. {
  304.     return delegate;
  305. }
  306.  
  307. - selectGroup:sender
  308. // target of inspector panel group selector PopUpList
  309. {
  310.     [popupOut setTitle:[[sender selectedCell] title]];
  311.     [inspectorPanel orderFront:self];
  312.     if ([delegate respondsTo:@selector(groupChanged:to:)]) 
  313.     {
  314.         [delegate groupChanged:self to:[sender selectedRow]];
  315.     }
  316.     return self;
  317. }
  318.  
  319. - revertPressed:sender
  320. // target of inspector panel Revert button
  321. {
  322.     if ([delegate respondsTo:@selector(inspectRevert)]) 
  323.     {
  324.         [delegate inspectRevert:self];
  325.     }
  326.     return self;
  327. }
  328.  
  329. - okPressed:sender
  330. // target of inspector panel OK button
  331. {
  332.     if ([delegate respondsTo:@selector(inspectOK)]) 
  333.     {
  334.         [delegate inspectOK:self];
  335.     }
  336.     return self;
  337. }
  338.  
  339. - showRevertOK
  340. {
  341.     [[inspectorPanel contentView] addSubview:revertOKOut];
  342.     [revertOKOut display];
  343.     return self;
  344. }
  345.  
  346. - hideRevertOK
  347. {
  348.     [revertOKOut removeFromSuperview];
  349.     // uncomment the following line to have the Revert/OK buttons
  350.     // automatically removed by displaying the contentView 
  351.     //    [[inspectorPanel contentView] display];
  352.     return self;
  353. }
  354.  
  355. - showGroupPopUp
  356. {
  357.     [[inspectorPanel contentView] addSubview:popupOut];
  358.     [popupOut display];
  359.     return self;
  360. }
  361.  
  362. - hideGroupPopUp
  363. {
  364.     [popupOut removeFromSuperview];
  365.     [[inspectorPanel contentView] display];
  366.     return self;
  367. }
  368. @end
  369.  
  370.